#include "mobjbuf.h"

void *g_ptr_group[10] = {NULL};

// 淘汰回调示例
int my_evict_callback(mobjbuf_t *objbuf, size_t require_size, void *userdata)
{
    (void)require_size;
    (void)userdata;

    printf("Space low, evicting data...\n");
    // 实际淘汰逻辑
    // 从 g_ptr_group 中找一个
    for (int i = 0; i < 10; i++)
    {
        if (g_ptr_group[i] != NULL)
        {
            printf("Evicted memory at[%d]: %p\n", i, g_ptr_group[i]);
            mobjbuf_free(objbuf, g_ptr_group[i]);
            g_ptr_group[i] = NULL;

            return MOBJBUF_EVICT_DONE; // 返回 MOBJBUF_EVICT_DONE 表示已释放空间
        }
    }

    return MOBJBUF_EVICT_NONE; // 返回 MOBJBUF_EVICT_NONE 表示未释放空间
}

int main()
{
    int index = 0;
    // void *ptr = NULL;
    int counts = 10;
    int alloc_size = 100;
    uint8_t buffer[2048]; // 预分配缓冲区
    mobjbuf_t mem_pool;

    // 初始化内存池
    if (mobjbuf_init(&mem_pool, buffer, sizeof(buffer)) != 0)
    {
        exit(1);
    }

    printf("mem_pool: " mobjbuf_format_s " \r\n", mobjbuf_format((&mem_pool)));

    while (counts--)
    {
        printf("///////////////////////////////////////////////////\r\n");
        printf("index: %d\r\n", index);

        // 找到 g_ptr_group 中一个为NULL的成员, 为其alloc一个空间
        g_ptr_group[index] = mobjbuf_alloc(&mem_pool, alloc_size, my_evict_callback, NULL);
        if (g_ptr_group[index] == NULL)
        {
            printf("Allocation failed!\n");
        }
        else
        {
            printf("Allocated %d bytes at %p\n", alloc_size, g_ptr_group[index]);
        }
        alloc_size += 50;
        index = (index + 1) % 10;

        mobjbuf_dump(&mem_pool); // 打印内存池状态
    }

    // 剩余空间全部释放掉
    for (int i = 0; i < 10; i++)
    {
        if (g_ptr_group[i] != NULL)
        {
            mobjbuf_free(&mem_pool, g_ptr_group[i]);
            g_ptr_group[i] = NULL;
        }
    }

    mobjbuf_dump(&mem_pool); // 打印内存池状态

    ///////////////////////////////////////////////////
    void *ptr1 = mobjbuf_alloc(&mem_pool, 100, my_evict_callback, NULL);
    if (ptr1 == NULL)
    {
        printf("Allocation failed!\n");
    }
    else
    {
        printf("Allocated %d bytes at %p\n", 100, ptr1);
    }

    mobjbuf_dump(&mem_pool); // 打印内存池状态

    void *ptr2 = mobjbuf_alloc(&mem_pool, 200, my_evict_callback, NULL);
    if (ptr2 == NULL)
    {
        printf("Allocation failed!\n");
    }
    else
    {
        printf("Allocated %d bytes at %p\n", 200, ptr2);
    }

    mobjbuf_dump(&mem_pool); // 打印内存池状态

    void *ptr3 = mobjbuf_alloc(&mem_pool, 300, my_evict_callback, NULL);
    if (ptr3 == NULL)
    {
        printf("Allocation failed!\n");
    }
    else
    {
        printf("Allocated %d bytes at %p\n", 300, ptr3);
    }

    mobjbuf_free_without_merge(&mem_pool, ptr1);
    mobjbuf_free_without_merge(&mem_pool, ptr2);
    mobjbuf_dump(&mem_pool); // 打印内存池状态

    mobjbuf_merge_free_blocks(&mem_pool);
    mobjbuf_dump(&mem_pool); // 打印内存池状态

    ptr1 = mobjbuf_alloc(&mem_pool, 400, my_evict_callback, NULL);
    if (ptr1 == NULL)
    {
        printf("Allocation failed!\n");
    }
    else
    {
        printf("Allocated %d bytes at %p\n", 400, ptr1);
    }

    mobjbuf_free_without_merge(&mem_pool, ptr3);
    mobjbuf_dump(&mem_pool); // 打印内存池状态

    ptr2 = mobjbuf_alloc(&mem_pool, 500, my_evict_callback, NULL);
    if (ptr2 == NULL)
    {
        printf("Allocation failed!\n");
    }
    else
    {
        printf("Allocated %d bytes at %p\n", 200, ptr2);
    }

    mobjbuf_merge_free_blocks(&mem_pool);
    mobjbuf_dump(&mem_pool); // 打印内存池状态

    mobjbuf_free(&mem_pool, ptr1);
    mobjbuf_free(&mem_pool, ptr2);
    mobjbuf_dump(&mem_pool); // 打印内存池状态

    return 0;
}